package middleware

import (
	"log"
	"runtime/debug"
	"stacks/utils"

	"github.com/gin-gonic/gin"
)

// CustomError 自定义错误类型
type CustomError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Details string `json:"details,omitempty"`
}

// Error 实现 error 接口
func (e *CustomError) Error() string {
	return e.Message
}

// NewCustomError 创建自定义错误
func NewCustomError(code int, message string) *CustomError {
	return &CustomError{
		Code:    code,
		Message: message,
	}
}

// ExceptionHandler 全局异常处理中间件
func ExceptionHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if r := recover(); r != nil {
				// 记录恐慌堆栈信息
				log.Printf("Panic recovered: %v\n%s", r, debug.Stack())

				// 根据错误类型返回相应的响应
				switch err := r.(type) {
				case *CustomError:
					// 自定义业务错误
					utils.Error(c, err.Code, err.Message)
				case error:
					// 标准错误类型
					utils.InternalError(c, "服务器内部错误")
				default:
					// 其他类型的恐慌
					utils.InternalError(c, "服务器内部错误")
				}

				// 终止请求处理
				c.Abort()
			}
		}()

		c.Next()

		// 处理非恐慌的HTTP错误
		if len(c.Errors) > 0 {
			for _, ginErr := range c.Errors {
				log.Printf("Gin error: %v", ginErr)
			}

			// 获取最后一个错误
			lastErr := c.Errors.Last()
			if lastErr != nil {
				switch lastErr.Type {
				case gin.ErrorTypeBind:
					// 参数绑定错误
					utils.BadRequest(c, "请求参数格式错误")
				case gin.ErrorTypeRender:
					// 响应渲染错误
					utils.InternalError(c, "响应渲染失败")
				case gin.ErrorTypePrivate:
					// 私有错误
					utils.InternalError(c, "服务器内部错误")
				case gin.ErrorTypePublic:
					// 公共错误
					utils.BadRequest(c, lastErr.Error())
				default:
					utils.InternalError(c, "服务器内部错误")
				}
			}
		}
	}
}

// 常用的业务错误定义
var (
	// ErrUnauthorized 认证相关错误
	ErrUnauthorized = NewCustomError(401, "未授权访问")
	ErrTokenExpired = NewCustomError(401, "Token已过期")
	ErrTokenInvalid = NewCustomError(401, "Token无效")

	// ErrForbidden 权限相关错误
	ErrForbidden = NewCustomError(403, "权限不足")

	// ErrNotFound 资源相关错误
	ErrNotFound         = NewCustomError(404, "资源不存在")
	ErrResourceConflict = NewCustomError(409, "资源冲突")

	// ErrValidation 业务逻辑错误
	ErrValidation    = NewCustomError(422, "参数验证失败")
	ErrBusinessLogic = NewCustomError(400, "业务逻辑错误")

	// ErrDatabase 系统错误
	ErrDatabase        = NewCustomError(500, "数据库操作失败")
	ErrExternalService = NewCustomError(502, "外部服务不可用")
	ErrRateLimit       = NewCustomError(429, "请求频率过高")
)

// Throw 抛出自定义错误（会触发恐慌）
func Throw(err *CustomError) {
	panic(err)
}

// ThrowWithDetails 抛出带详细信息的自定义错误
func ThrowWithDetails(code int, message, details string) {
	panic(&CustomError{
		Code:    code,
		Message: message,
		Details: details,
	})
}

// SafeExecute 安全执行函数，捕获恐慌并返回错误
func SafeExecute(fn func() error) (err error) {
	defer func() {
		if r := recover(); r != nil {
			switch e := r.(type) {
			case *CustomError:
				err = e
			case error:
				err = e
			default:
				err = NewCustomError(500, "未知错误")
			}
		}
	}()

	err = fn()
	return
}
